package com.demo.uitls;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * @Author DongXL
 * @Create 2017-09-15 15:16
 */
public enum SignUtils {

    INSTANCE;

    private static final Logger log = LoggerFactory.getLogger(SignUtils.class);

    public String sign(Object o, String secret) {
        Map<String, String> map = null;
        try {
            map = BeanUtils.describe(o);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            log.error("BeanUtils.describe object error", e);
        }
        if (MapUtils.isNotEmpty(map)) {
            for (String key : Arrays.asList("sign", "class")) {
                map.remove(key);
            }
        }
        if (MapUtils.isEmpty(map)) {
            return null;
        }
        Set<String> sortedKeySet = getSortedKeySet(map);
        String signString = getSignString(map, sortedKeySet, secret);
        return sign(signString);
    }

    /**
     * 加密
     *
     * @param str
     * @return
     */
    private String sign(String str) {
        return StringUtils.upperCase(DigestUtils.md5Hex(str));
    }

    /**
     * map的key升序排列，返回keySet
     *
     * @param map
     * @return
     */
    private Set<String> getSortedKeySet(Map<String, String> map) {
        TreeMap sortedMap = new TreeMap(map);
        return sortedMap.keySet();
    }

    /**
     * 待加密字符串
     *
     * @param map
     * @param sortedKeySet
     * @param secret
     * @return
     */
    private String getSignString(Map<String, String> map, Set<String> sortedKeySet, String secret) {
        StringBuffer sb = new StringBuffer();
        sb.append(secret);
        for (String key : sortedKeySet) {
            String value = map.getOrDefault(key, "");
            sb.append(key).append(value);
        }
        sb.append(secret);
        return sb.toString();
    }

}
